package csel.view;

import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JToggleButton;
import javax.swing.JPanel;
import javax.swing.ImageIcon;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.List;

import csel.model.Entity;
import csel.model.Inventory;
import csel.model.EquippableItem;
import csel.model.Observer;
import csel.model.TakeableItem;
import csel.model.UseableItem;


/*
 * Reasons for Existence: Encapsulates the part of the status viewport that displays the player's 
 * inventory contents. Provides the controller information about user interaction with the inventory 
 * section of the status viewport.  This is a distinct function and should be differentiated from the 
 * other features of the StatusViewport.
 * 
 * @author Alex
 */

public class InventoryViewer extends JPanel implements Observer
{
	private static final long serialVersionUID = 1L;

	ButtonGroup itemButtons;
	LinkedList<JToggleButton> equippableButtons;
	LinkedList<JToggleButton> useableButtons;

	JButton use;
	JButton drop;
	JButton equip;

	JPanel buttonPane;
	JPanel itemsPane;
	JPanel groupPane;

	//only responsible for enabling/disabling the use and equip buttons based on selected item
	InventoryScreenManager invListener = new InventoryScreenManager();

	public InventoryViewer(Entity e, ActionListener a)
	{
		e.addObserver(this);

		buttonPane = new JPanel();
		itemsPane = new JPanel();
		groupPane = new JPanel();
		buttonPane.setLayout(new BoxLayout(buttonPane,BoxLayout.X_AXIS));

		use = new JButton("Use");
		equip = new JButton("Equip");
		drop = new JButton("Drop");
		use.setActionCommand("stuse");
		equip.setActionCommand("stequip");
		drop.setActionCommand("stdrop");
		use.addActionListener(a);
		equip.addActionListener(a);
		drop.addActionListener(a);

		buttonPane.setOpaque(false);
		
		buttonPane.add(use);
		buttonPane.add(drop);
		buttonPane.add(equip);
		use.setFocusable(false);
		equip.setFocusable(false);
		drop.setFocusable(false);

		GridBagConstraints c = new GridBagConstraints();
		c.gridx = 0;
		c.gridy = 0;

		groupPane.setLayout(new GridBagLayout());
		groupPane.add(buttonPane,c);
		groupPane.setOpaque(false);


		add(groupPane,c);
		modelUpdate(e);
	}

	public TakeableItem[] getSelectedItems()
	{
		LinkedList<TakeableItem> selectedItems = new LinkedList<TakeableItem>();

		//gets all selected equippable item buttons
		int size = equippableButtons.size();
		for (int a = 0; a < size; ++a)
		{
			if (equippableButtons.get(a).getSelectedObjects() != null)
				selectedItems.add((TakeableItem) equippableButtons.get(a).getClientProperty("myItem"));
		}

		//gets all selected useable item buttons
		size = useableButtons.size();
		for (int a = 0; a < size; ++a)
		{
			if (useableButtons.get(a).getSelectedObjects() != null)
				selectedItems.add((TakeableItem) useableButtons.get(a).getClientProperty("myItem"));
		}

		//builds an array of the items corresponding to the selected buttons
		Object[] items = selectedItems.toArray();
		int itemsLength = items.length;
		TakeableItem[] takeables = new TakeableItem[itemsLength];
		for (int a = 0; a < itemsLength; ++a)
			takeables[a] = (TakeableItem) items[a];

		//returns the selected items
		if (takeables.length != 0)
			return takeables;
		return null;
	}

	public void modelUpdate(Object o)
	{
		Entity e = ((Entity) o);
		Inventory inv = e.getInventory();
		if(inv.hasChanged())
		{
			//		removeAll();
			JPanel titemsPane = new JPanel();

			List<EquippableItem> eList = inv.getEquippableItems();
			List<UseableItem> uList = inv.getUseableItems();

			//		this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));

			itemButtons = new ButtonGroup();
			useableButtons = new LinkedList<JToggleButton>();
			equippableButtons = new LinkedList<JToggleButton>();

			int size = eList.size();
			titemsPane.setLayout(new GridBagLayout());
			GridBagConstraints c = new GridBagConstraints();
			int rowNum = 1;

			//adds all equippable item buttons
			for (int b = 0; b < size; ++b)
			{
				JToggleButton j = new JToggleButton(new ImageIcon(RepresentationFactory.getInstance().get(eList.get(b)).getSimpleImage()));
				j.setActionCommand("equippable");
				j.addActionListener(invListener);
				j.putClientProperty("myItem", (TakeableItem) eList.get(b));
				j.setPreferredSize(new Dimension(50,50));
				equippableButtons.add(j);
				itemButtons.add(j);

				c.gridx = 0;
				c.gridy = rowNum;
				titemsPane.add(j,c);
				c.gridx = 1;
				c.gridy = rowNum++;
				JLabel item1 = new JLabel(eList.get(b).getDescription());
				item1.setForeground(Color.WHITE);
				titemsPane.add(item1,c);
			}

			//adds all useable item buttons
			size = uList.size();
			for (int b = 0; b < size; ++b)
			{
				JToggleButton j = new JToggleButton(new ImageIcon(RepresentationFactory.getInstance().get(uList.get(b)).getSimpleImage()));
				j.setActionCommand("useable");
				j.addActionListener(invListener);
				j.putClientProperty("myItem", uList.get(b));
				j.setMaximumSize(new Dimension(50,50));
				j.setFocusable(false);
				useableButtons.add(j);
				itemButtons.add(j);

				c.gridx = 0;
				c.gridy = rowNum;
				titemsPane.add(j,c);
				c.gridx = 1;
				c.gridy = rowNum++;
				JLabel item2 = new JLabel(uList.get(b).getDescription());
				item2.setForeground(Color.WHITE);
				titemsPane.add(item2,c);
			}

			titemsPane.setOpaque(false);
			groupPane.remove(itemsPane);
			itemsPane = titemsPane;
			c.gridy = 1;
			c.gridx = 0;
			groupPane.add(itemsPane,c);

			groupPane.revalidate();
		}
	}

	public void setEntity(Entity e)
	{
		e.addObserver(this);
		modelUpdate(e);
	}

	//only responsible for enabling/disabling the use and equip buttons based on the type
	//of item that is selected.
	private class InventoryScreenManager implements ActionListener
	{
		public void actionPerformed(ActionEvent e)
		{
			if (e.getActionCommand().equals("equippable"))
			{
				use.setEnabled(false);
				equip.setEnabled(true);
			}
			else
			{
				use.setEnabled(true);
				equip.setEnabled(false);
			}
		}
	}

	
	private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException
	{
		throw new java.io.NotSerializableException("AvatarViewer should not be serialized.");
	}
	
	private void readObject(java.io.ObjectInputStream in) throws java.io.IOException
	{
		throw new java.io.NotSerializableException("AvatarViewer should not be serialized.");
	}
}